package org.spring.springboot.app.user.sysuser.service.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.text.CharacterPredicates;
import org.apache.commons.text.RandomStringGenerator;
import org.spring.springboot.app.base.Constants;
import org.spring.springboot.app.base.R;
import org.spring.springboot.app.base.Type;
import org.spring.springboot.app.user.sysuser.domain.vo.MailSendReqVO;
import org.spring.springboot.app.user.sysuser.domain.vo.MailSendResVO;
import org.spring.springboot.app.user.sysuser.domain.vo.ValidMailReqVO;
import org.spring.springboot.app.user.sysuser.domain.vo.modifyMailPasswordReqVO;
import org.spring.springboot.app.user.sysuser.service.IFindMailPassword;
import org.spring.springboot.app.mail.mail.service.ISysuBindService;
import org.spring.springboot.app.user.sysuser.dao.SysUserDao;
import org.spring.springboot.app.user.sysuser.domain.po.SysUserPO;
import org.spring.springboot.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class FindMailPasswordImpl implements IFindMailPassword {

    private static final Log log = LogFactory.getLog(FindMailPasswordImpl.class);

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    private SysUserDao sysUserDao;

    @Autowired
    private ISysuBindService emailService;

    @Override
    public R modifyPassword(modifyMailPasswordReqVO modifyMailPasswordReqVO) {
        R r = new R();
        if (!r.valid(modifyMailPasswordReqVO)) {
            return r;
        }
        SysUserPO po = sysUserDao.findByLoginId(modifyMailPasswordReqVO.getLoginId());
        if (po == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("loginId", "账号不存在");
            return r;
        }
        String mailCode = redisUtils.getString(Constants.MAIL_SEND_CODE_REDIS_KEY + po.getId());
        if (mailCode == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("mailCode", "邮箱验证码已过期");
            return r;
        }
        if (!mailCode.equalsIgnoreCase(modifyMailPasswordReqVO.getMailCode())) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("mailCode", "邮箱验证码不正确");
            return r;
        }
        SysUserPO user = new SysUserPO();
        user.setId(po.getId());
        user.setPassword(modifyMailPasswordReqVO.getPassword());
        user.setUpdateBy(po.getId());
        user.setUpdateDate(new Date());
        int i = sysUserDao.updateByPrimaryKeySelective(user);
        if (i == 0) {
            r.setType(Type.OperError);
            return r;
        }
        return r;
    }


    @Override
    public R<MailSendResVO> sendMail(MailSendReqVO mailSendReqVO) {
        R<MailSendResVO> r = new R<MailSendResVO>();
        if (!r.valid(mailSendReqVO)) {
            return r;
        }

        SysUserPO po = sysUserDao.findByLoginId(mailSendReqVO.getLoginId());

        if (po == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("loginId", "用户不存在");
            return r;
        }


        if (redisUtils.hasStringKey(Constants.MAIL_SEND_OUT_TIME_REDIS_KEY + po.getId())) {
            r.setType(Type.OperError);
            r.setMessage("验证码每60秒只能发送一次");
            return r;
        }

        String mailCode = redisUtils.getString(Constants.MAIL_SEND_IMAGE_CODE_REDIS_KEY + mailSendReqVO.getImageCaptchaToken());
        if (mailCode == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("imageCode", "图片验证码已过期,请点击图片验证码刷新");
            return r;
        }
        if (!mailCode.equalsIgnoreCase(mailSendReqVO.getImageCode())) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("imageCode", "图片验证码不正确");
            return r;
        }

        if (po.getEmail() == null || po.getEmail().length() == 0) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("loginId", "用户还未绑定邮箱,请使用其它方式找回,或者联系客服");
            return r;
        }
        String code = new RandomStringGenerator.Builder().withinRange('0', 'Z').filteredBy(CharacterPredicates.DIGITS, CharacterPredicates.LETTERS).build().generate(4);
        String html = "你的GTA后台管理系统的找回验证码为<span style=\"color:red;\">" + code + "</span>如果这不是你本人的操作,请忽略此条邮件";
        try {
            emailService.mainEmail("GTA后台管理系统密码找回", html, po.getEmail());
        } catch (Exception e) {
            r.setType(Type.OperError);
            r.setMessage("发送邮件失败,请稍后在试或者联系客服");
            log.error(e);
            return r;
        }
        redisUtils.setString(Constants.MAIL_SEND_OUT_TIME_REDIS_KEY + po.getId(), new Date().getTime() + "", 60, TimeUnit.SECONDS);
        redisUtils.setString(Constants.MAIL_SEND_CODE_REDIS_KEY + po.getId(), code, 10 * 60, TimeUnit.SECONDS);
        MailSendResVO vo = new MailSendResVO();
        vo.setEmail(po.getEmail());
        r.setData(vo);
        return r;
    }

    @Override
    public R<MailSendResVO> validMailCode(ValidMailReqVO vo) {
        R<MailSendResVO> r = new R<MailSendResVO>();
        if (!r.valid(vo)) {
            return r;
        }
        SysUserPO po = sysUserDao.findByLoginId(vo.getLoginId());
        if (po == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("loginId", "账号不存在");
            return r;
        }
        if (po.getEmail() == null || po.getEmail().length() == 0) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("loginId", "用户还未绑定邮箱,请使用其它方式找回,或者联系客服");
            return r;
        }
        String mailCode = redisUtils.getString(Constants.MAIL_SEND_CODE_REDIS_KEY + po.getId());
        if (mailCode == null) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("mailCode", "邮箱验证码已过期,请重新发送");
            return r;
        }
        if (!mailCode.equalsIgnoreCase(vo.getMailCode())) {
            r.setType(Type.ParamValidateFail);
            r.addMessage("mailCode", "邮箱验证码错误");
            return r;
        }
        MailSendResVO mailSendResVO = new MailSendResVO();
        mailSendResVO.setEmail(po.getEmail());
        return r;
    }
}
